#include "Win32/WindowsUtilities.h"
#include "NezhaEngine.h"

namespace Nezha
{
#ifdef NZOS_WIN32

	class Win32SystemEventQueue : public SystemEventQueue
	{
	public:
		virtual void update()
		{
			MSG msg;
			while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
			{
				if(msg.message == WM_QUIT)
				{
					// TODO post quit message?

					mEngine->notifySystemQuitEvent();
					break;
				}

				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}

		Win32SystemEventQueue()
		{
			mEngine = NezhaEngine::getSingletonPtr();
		}

		NezhaEngine* mEngine;
	};

	SystemEventQueue* CreateDefaultSystemEventQueue()
	{
		return NZ_New Win32SystemEventQueue();
	}

	NZ_NativeWindow InternalCreateNativeWindow(const EngineConfig& cfg)
	{
		DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
		DWORD dwStyleEx = 0;
		//MONITORINFOEX monitorInfoEx;
		//RECT rc;

		NZ_NativeWindow hWnd = NULL;

		if(!cfg.mWindowed)
		{
			dwStyle |= WS_POPUP;
			dwStyleEx |= WS_EX_TOPMOST;

		}
		else
		{
			if(cfg.mParentWindow)
			{
				dwStyle |= WS_CHILD;
			}
			else
			{
				Str_KeyVals::const_iterator it = cfg.mExtraSettings.find("border");
				if(it != cfg.mExtraSettings.end())
				{
					if(it->second == "none")
					{
						dwStyle |= WS_POPUP;
					}
					else if(it->second == "fixed")
					{
						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
					}
					else
					{
						dwStyle |= WS_OVERLAPPEDWINDOW;
					}
				}
				else
				{
					dwStyle |= WS_OVERLAPPEDWINDOW;
				}
			}
		}

		HINSTANCE hInst = GetModuleHandle(NULL);
		WNDCLASS wc = { CS_OWNDC, WindowsUtilities::NezhaWindowsProc, 0, 0, hInst,
			LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
			(HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "NezhaEnginewWin32" };

		RegisterClass(&wc);

		RECT rc = {0, 0, cfg.mScreenWidth-1, cfg.mScreenHeight-1};
		AdjustWindowRect(&rc, dwStyle, false);

		int adjustedW = rc.right - rc.left + 1;
		int adjustedH = rc.bottom - rc.top + 1;

		int posX = cfg.mWindowPosX == -1 ? (GetSystemMetrics(SM_CXSCREEN) - adjustedW) / 2 : cfg.mWindowPosX;
		int posY = cfg.mWindowPosY == -1 ? (GetSystemMetrics(SM_CYSCREEN) - adjustedH) / 2 : cfg.mWindowPosY;

		hWnd = (NZ_NativeWindow)CreateWindowEx(dwStyleEx, "NezhaEnginewWin32", cfg.mAppName.c_str(),
			dwStyle, posX, posY, adjustedW, adjustedH,
			(HWND)cfg.mParentWindow, 0, hInst, NULL);

		return hWnd;
	}

	LRESULT CALLBACK WindowsUtilities::NezhaWindowsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		// TODO

		switch(uMsg)
		{
		case WM_DESTROY:
			{
				PostQuitMessage(0);
				return 0;
			}
		}

		return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
	}

#endif //end NZOS_WIN32
}